package com.leiyuee.mybatis.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class ModelUtils {

    /**
     * 判断一个对象是否为空
     * @param sv
     * @return
     */
    public static boolean isEmpty(Object sv) {
        if (sv == null) {
            return true;
        }
        if (sv.getClass().isArray()) {
            return ((Object[]) sv).length == 0;
        }
        if (sv instanceof Collection) {
            return ((Collection) sv).isEmpty();
        }
        if (sv instanceof Map) {
            return ((Map) sv).isEmpty();
        }
        if (sv instanceof String) {
            return sv.toString().trim().equals("");
        }
        return sv.getClass().equals(Object.class);
    }

    public static boolean isNotEmpty(Object o) {
        return !isEmpty(o);
    }




    public static <T> T transMapObject2Bean(T obj,Map<String,Object> map) {
        return transMap2Bean(obj,null,mapObject2StringConverter(map));
    }

    public static <T> T transMap2Bean(T obj,Map<String,String> map) {
        return transMap2Bean(obj,null,map);
    }

    public static <T> T transMap2Bean(T obj, Class<T> clazz,Map<String,String> map) {

        try {

            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Class claz = field.getType();
                String value = map.get(field.getName());
                if(StringUtils.isNotBlank(value)) {
                    if (claz == Integer.class) {
                        field.set(obj,Integer.valueOf(value));
                    } else if (claz == BigDecimal.class) {
                        field.set(obj,new BigDecimal(value));
                    } else if (claz == Long.class) {
                        field.set(obj,Long.valueOf(value));
                    } else if (claz == Short.class) {
                        field.set(obj,Short.valueOf(value));
                    } else if (claz == String.class) {
                        field.set(obj,value);
                    } else if (claz == Date.class) {
                        Date date = dateConverter(value);
                        field.set(obj,date);
                    } else if (claz == Byte.class){
                        int val = Integer.valueOf(value);
                        field.set(obj,(byte)val);
                    }
                }
            }

        } catch (IllegalAccessException e) {
            e.printStackTrace();
            log.error("ModelUtils transMap2Bean error:"+e.getMessage());
        } catch (ParseException e) {
            e.printStackTrace();
            log.error("ModelUtils transMap2Bean error"+e.getMessage());
        } catch (Exception e){
            e.printStackTrace();
            log.error("ModelUtils transMap2Bean error"+e.getMessage());
        }

        return obj;
    }

    private static Date dateConverter(String value) throws ParseException {
        Date date = null;
        if(value.contains("Z")){
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
            sf.setTimeZone(TimeZone.getTimeZone("UTC"));
            date = sf.parse(value);
        }else {
            String format;
            if (value.length()==10)// yyyy-MM-dd
                format = "yyyyMMdd";
            else
                format = "yyyyMMddHHmmss";

            SimpleDateFormat sdf = new SimpleDateFormat(format);
            value = StringUtils.replaceEachRepeatedly(value,
                    new String[] { "-", ":", ".", " ", "/" }, new String[] { "", "", "", "", "" });
            date = sdf.parse(value);
        }
        return date;
    }


    // Map --> Bean 1: 利用Introspector,PropertyDescriptor实现 Map --> Bean
/*    public static void transMap2Bean(Map<String, String> map, Object obj) {

        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            if (null != map) {
                for (PropertyDescriptor property : propertyDescriptors) {
                    Class claz = property.getPropertyType();
                    if(null!=map.get(property.getName())) {
                        Object value = null;
                        if (claz == Integer.class) {
                            value = Integer.valueOf(map.get(property.getName()));
                        } else if (claz == BigDecimal.class) {
                            value = new BigDecimal(map.get(property.getName()));
                        } else if (claz == Long.class) {
                            value = Long.valueOf(map.get(property.getName()));
                        } else if (claz == Short.class) {
                            value = Short.valueOf(map.get(property.getName()));
                        } else if (claz == String.class) {
                            value = map.get(property.getName());
                        } else if (claz == Date.class) {
                            value =  DateUtil.parseDate(map.get(property.getName()));
                        }
                        if (null != value) {
                            Method setter = property.getWriteMethod();
                            setter.invoke(obj, value);
                        }
                    }
                }
            }

        } catch (Exception e) {
            System.out.println("transMap2Bean Error " + e);
        }

    }*/

    // Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
    public static Map<String, Object> transBean2Map(Object obj) {

        if(obj == null){
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, value==null?"":value);
                }
            }
        } catch (Exception e) {
            //LogUtils.info("transBean2Map Error " + e);
        }

        return map;

    }

    // Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
    public static Map<String, Object> transBean2MapWithoutNullProperty(Object obj) {

        if(obj == null){
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    if(value!=null)
                        map.put(key,value);
                }
            }
        } catch (Exception e) {
            //LogUtils.info("transBean2Map Error " + e);
        }

        return map;

    }

    public static Map<String,String> mapObject2StringConverter(Map<String,Object> map){
        return map.entrySet().stream()
             .filter(m -> m.getKey() != null && m.getValue() !=null)
             .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toString()));
    }

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class clazz = Class.forName("com.gdcn.terminaltest.web.model.testcard.CardInfo");
        Object obj = clazz.newInstance();//通过反射创建对象

// 调用getDeclaredField("name") 取得name属性对应的Field对象
        Field f = clazz.getDeclaredField("id");

// 取消属性的访问权限控制，即使private属性也可以进行访问。
        f.setAccessible(true);
// 调用get()方法取得对应属性值。
        System.out.println(f.get(obj));  //相当于obj.getName();
// 调用set()方法给对应属性赋值。
        f.set(obj, 1111);  //相当于obj.setName("lkl");
// 调用get()方法取得对应属性修改后的值。
        System.out.println(f.get(obj));
    }

}
